#region Copyright note and modification history

/*
-----------------------------------------------------------------------------
Copyright (c) 2006 HSI Inc. All Rights Reserved.

PROPRIETARY NOTICE: This software has been provided pursuant to a
License Agreement that contains restrictions on its use. This software
contains valuable trade secrets and proprietary information of
HSI Inc and is protected by Federal copyright law. It may not
be copied or distributed in any form or medium, disclosed to third parties,
or used in any manner that is not provided for in said License Agreement,
except with the prior written authorization of HSI Inc.

-----------------------------------------------------------------------------
$Log: /CoreServices/Hsi/Drawing/RectangleExtensions.cs $
 * 
 * 3     9/14/07 5:22p Nathan_stults
 * 
 * 2     2/22/07 11:35a Alex_wang
 * Added MeasureDisplayStringWidth method.
-----------------------------------------------------------------------------
*/

#endregion

using System;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace SimplePushpinGenerator
{
    /// <summary>
    /// Summary description for DrawingDrawingHelperity.
    /// </summary>
    public static class RectangleExtensions
    {
        public static Rectangle Grow(this Rectangle source, int percent)
        {
            return Grow(source, percent, percent);
        }

        public static Rectangle Grow(this Rectangle source, int widthPercent, int heightPercent)
        {
            int widthGrowth = Convert.ToInt32(source.Width*(widthPercent/100.0));
            int heightGrowth = Convert.ToInt32(source.Height*(heightPercent/100.0));
            Rectangle newRect = source;
            newRect.Inflate(widthGrowth, heightGrowth);
            return newRect;
        }

        public static Rectangle Shrink(this Rectangle source, int percent)
        {
            return Grow(source, percent*-1);
        }

        public static Rectangle Shrink(this Rectangle source, int widthPercent, int heightPercent)
        {
            return Grow(source, widthPercent*-1, heightPercent*-1);
        }

        public static void CenterInside(this Rectangle outerRect, ref Rectangle targetRect)
        {
            Point center = GetCenterPoint(outerRect);
            targetRect.X = center.X - targetRect.Width/2;
            targetRect.Y = center.Y - targetRect.Height/2;
        }

        public static Point GetCenterPoint(this Rectangle rectangle)
        {
            return new Point(rectangle.Width/2 + rectangle.X, rectangle.Height/2 + rectangle.Y);
        }

       
        /// <summary>
        /// Get the desired Rounded Rectangle path. 
        /// </summary>
        /// <param name="baseRect"></param>
        /// <param name="radius"></param>
        /// <returns></returns>
        public static GraphicsPath GetRoundedRect(this RectangleF baseRect,
                                                  float radius)
        {
            // if corner radius is less than or equal to zero, 
            // return the original rectangle 
            if (radius <= 0.0F)
            {
                var mPath = new GraphicsPath();
                mPath.AddRectangle(baseRect);
                mPath.CloseFigure();
                return mPath;
            }

            // if the corner radius is greater than or equal to 
            // half the width, or height (whichever is shorter) 
            // then return a capsule instead of a lozenge 
            if (radius >= (Math.Min(baseRect.Width, baseRect.Height)) / 2.0)
                return GetCapsule(baseRect);

            // create the arc for the rectangle sides and declare 
            // a graphics path object for the drawing 
            float diameter = radius * 2.0F;
            var sizeF = new SizeF(diameter, diameter);
            var arc = new RectangleF(baseRect.Location, sizeF);
            var path = new GraphicsPath();

            // top left arc 
            path.AddArc(arc, 180, 90);

            // top right arc 
            arc.X = baseRect.Right - diameter;
            path.AddArc(arc, 270, 90);

            // bottom right arc 
            arc.Y = baseRect.Bottom - diameter;
            path.AddArc(arc, 0, 90);

            // bottom left arc
            arc.X = baseRect.Left;
            path.AddArc(arc, 90, 90);

            path.CloseFigure();
            return path;
        }

        /// <summary>
        /// Gets a caption balloon path
        /// </summary>
        /// <param name="baseRect"></param>
        /// <param name="radius"></param>
        /// <param name="pointerTip"></param>
        /// <param name="pointerOffset"></param>
        /// <param name="pointerBaseWidth"></param>
        /// <returns></returns>
        public static GraphicsPath GetCaptionBalloon(this RectangleF baseRect,
                                                     float radius, Point pointerTip, float pointerOffset,
                                                     float pointerBaseWidth)
        {
            // if corner radius is less than or equal to zero, 
            // return the original rectangle 
            if (radius <= 0.0F)
            {
                var mPath = new GraphicsPath();
                mPath.AddRectangle(baseRect);
                mPath.CloseFigure();
                return mPath;
            }

            // if the corner radius is greater than or equal to 
            // half the width, or height (whichever is shorter) 
            // then return a capsule instead of a lozenge 
            if (radius >= (Math.Min(baseRect.Width, baseRect.Height)) / 2.0)
                return GetCapsule(baseRect);

            // create the arc for the rectangle sides and declare 
            // a graphics path object for the drawing 
            float diameter = radius * 2.0F;
            var sizeF = new SizeF(diameter, diameter);
            var arc = new RectangleF(baseRect.Location, sizeF);
            var path = new GraphicsPath();

            // top left arc 
            path.AddArc(arc, 180, 90);

            // top right arc 
            arc.X = baseRect.Right - diameter;
            path.AddArc(arc, 270, 90);

            // bottom right arc 
            arc.Y = baseRect.Bottom - diameter;
            path.AddArc(arc, 0, 90);

            //Add Pointer
            path.AddLine(baseRect.Right - pointerOffset, baseRect.Bottom, pointerTip.X, pointerTip.Y);
            path.AddLine(pointerTip.X, pointerTip.Y, baseRect.Right - pointerOffset - pointerBaseWidth, baseRect.Bottom);

            // bottom left arc
            arc.X = baseRect.Left;
            path.AddArc(arc, 90, 90);

            path.CloseFigure();
            return path;
        }


        /// <summary>
        /// Gets the desired Capsular path.
        /// </summary>
        /// <param name="baseRect"></param>
        /// <returns></returns>
        private static GraphicsPath GetCapsule(this RectangleF baseRect)
        {
            RectangleF arc;
            var path = new GraphicsPath();
            try
            {
                float diameter;
                if (baseRect.Width > baseRect.Height)
                {
                    // return horizontal capsule 
                    diameter = baseRect.Height;
                    var sizeF = new SizeF(diameter, diameter);
                    arc = new RectangleF(baseRect.Location, sizeF);
                    path.AddArc(arc, 90, 180);
                    arc.X = baseRect.Right - diameter;
                    path.AddArc(arc, 270, 180);
                }
                else if (baseRect.Width < baseRect.Height)
                {
                    // return vertical capsule 
                    diameter = baseRect.Width;
                    var sizeF = new SizeF(diameter, diameter);
                    arc = new RectangleF(baseRect.Location, sizeF);
                    path.AddArc(arc, 180, 180);
                    arc.Y = baseRect.Bottom - diameter;
                    path.AddArc(arc, 0, 180);
                }
                else
                {
                    // return circle 
                    path.AddEllipse(baseRect);
                }
            }
            catch
            {
                path.AddEllipse(baseRect);
            }
            finally
            {
                path.CloseFigure();
            }
            return path;
        }

    }
}